# -*- coding: utf-8 -*-
# @Author  : 喵奇葩


class ReplaceSelect:
    """
    替换选择的解题代码，不是真正的算法
    根据https://blog.csdn.net/chuanglan/article/details/79043533
    修改之后 现在已经可以算 多个run的了
    """

    # memo_len=3
    # input_lst = []
    # memo_lst = []
    # is_fixed=[]
    # now_index = 0

    def __init__(self, input_lst, memo_len):
        self.input_lst = input_lst
        self.memo_lst = []
        self.memo_len = memo_len
        self.tape = []
        self.input_lst_len = len(self.input_lst)
        self.now_index = 0
        self.sequences = []
        # self.is_fixed=[0 for i in range(len((self.input_lst)))]
        self.is_fixed = [False for i in range(self.input_lst_len)]
        print(f"先把前面{memo_len}个放在优先队列里面")
        print("从输入序列里拿东西出来,放到优先队列里面最小的数字的位置,要是输入序列里拿东西比优先队列里原来的数字小,\n"
              "这个地方会被框住,就是下一轮之前,都不会去动他了")
        for i in range(memo_len):
            self.memo_lst.append(self.input_lst[i])

        self.now_index += memo_len
        # self.run()
        print("一开始的输入序列: ", end="")
        self.print_input_lst()
        # print("一开始的优先队列", self.memo_lst)
        self.print_memo()

    def run(self):
        cnt = 0
        while self.now_index < self.input_lst_len:
            self.take_min_push_next()
            print()
            cnt += 1
            if cnt > 100:
                print("循环太多，可能有错误，检查看看bug")
                break

        # self.take_min_push_next()
        cnt = 0
        while self.take_min():
            print()
            cnt += 1
            if cnt > 100:
                print("循环太多，可能有错误，检查看看bug")
                break
        self.show_sequences()
        # print("现在输出磁带里有几个递增的序列，就可以数了，还有最后框柱的可能还有一个序列")
        self.memo_sort()

    def show_sequences(self):
        print("输出磁带：",self.tape)
        min_num = self.tape[0]
        tmp_lst = []
        for num in self.tape:

            if num >= min_num:
                tmp_lst.append(num)
                min_num = num

            else:

                self.sequences.append(tmp_lst)
                min_num = num
                # tmp_lst.clear()
                # 这里是引用 就算push进去了，还是会改变的
                # 所以这里写 clear 是错的
                tmp_lst = [min_num]

        if len(tmp_lst) > 0:
            self.sequences.append(tmp_lst)
        print(f"有{len(self.sequences)}个序列，不包括最后的被定住的那些")
        print(self.sequences)

    def print_fixed(self):
        """
        一开始是用来标记被框柱的数字的，但是后来看了
        https://blog.csdn.net/chuanglan/article/details/79043533
        这篇博客 发现他的用（）表示的方法更好，所以就用他的方法了
        :return:
        """
        # print(" "*8,end="")
        print("被框柱:  ", end="")
        # print(self.is_fixed)
        for fixed in self.is_fixed:
            if fixed:
                print(" ^  ", end="")
            else:
                print("    ", end="")
        print()

    def take_min(self):
        min_index = self.get_min_index()
        if min_index == -1:
            print("没有最小的可以拿了")
            return False
        else:
            print(f"从内存缓冲拿出最小的{self.memo_lst[min_index]}")
            self.tape.append(self.memo_lst[min_index])
            # out_num = self.memo_lst[min_index]
            self.memo_lst[min_index] = None

        # print("优先队列", self.memo_lst)
        # self.print_fixed()
        self.print_memo()
        # print(self.memo_lst)
        print("输出磁带:", self.tape)
        # print( self.tape)
        # self.now_index += 1
        return True

    def print_memo(self):
        cnt = 0
        print("内存缓冲: [", end="")
        for num in self.memo_lst:
            if self.is_fixed[cnt]:
                print(f"({num}),", end=" ")
            else:
                print(str(num) + ",", end=" ")
            cnt += 1
        print("]")

    def take_memo_show(self, min_index):
        cnt = 0
        print("内存缓冲，$$括起来的是找到的最小数字的位置: [", end="")
        for num in self.memo_lst:
            if min_index == cnt:
                if self.is_fixed[cnt]:
                    print(f"$({num})$,", end=" ")
                else:
                    print(f"${num}$,", end=" ")
            elif self.is_fixed[cnt]:
                print(f"({num}),", end=" ")

            else:
                print(str(num) + ",", end=" ")
            cnt += 1
        print("]")

    def take_min_push_next(self):
        min_index = self.get_min_index()

        # self.print_memo()
        if min_index == -1:
            print("没有最小的可以拿了，全都框柱了")
        else:
            self.take_memo_show(min_index)
            print(f"从内存缓冲拿出最小的{self.memo_lst[min_index]}，放到输出磁带里面。")
            self.tape.append(self.memo_lst[min_index])
            print("输出磁带:", self.tape)

            print("输入序列: ", end="")
            self.print_input_lst()
            print(f"然后从输入序列拿出下一个数字：{self.input_lst[self.now_index]}，放到内存缓冲刚才空出来的位置")


        # todo
        push_num = self.input_lst[self.now_index]
        out_num = self.memo_lst[min_index]
        self.memo_lst[min_index] = self.input_lst[self.now_index]

        if out_num > push_num:
            self.is_fixed[min_index] = True

        # self.memo_lst[min_index]=self.input_lst[self.now_index]
        # self.input_lst.pop_front()
        # del self.input_lst[0]
        self.now_index += 1
        self.take_memo_show(min_index)

        print("输入序列,第一个被拿走了: ", end="")
        self.print_input_lst()
        # print("优先队列", self.memo_lst)
        # self.print_fixed()
        # self.print_memo()

        # print(self.memo_lst)
        print("输出磁带:", self.tape)
        # print( self.tape)

    # https://blog.csdn.net/chuanglan/article/details/79043533
    def print_input_lst(self):
        # for i in range(self.now_index,self.input_lst_len):
        #     print()
        print(self.input_lst[self.now_index: self.input_lst_len])

    def memo_sort(self):
        print("最后内存的再排序一下,作为最后的run，如果没有就当做没有最后的run")
        want_sort_list = []
        for num in self.memo_lst:
            if num is None: continue
            want_sort_list.append(num)
        print(sorted(want_sort_list))

    def get_min_index(self):
        min_index = 0
        # if self.is_fixed[0]:min_index=1
        # todo 前面有个被框柱的12  我 94 就不会是最小的 ，12), 94, 96
        # 此问题已经解决
        # todo ：[None, (15), 99, 58, ] 这种情况 直接跳过了 有问题啊，把while循环改了，
        #  感觉解决问题了，但是后续肯定还有更多问题的
        # 先是把定住的那些跳过了
        while min_index < self.memo_len:
            if self.is_fixed[min_index]:
                min_index += 1
            elif self.memo_lst[min_index] is None:
                min_index += 1
            else:
                break
        # while min_index < self.memo_len and self.is_fixed[min_index]:
        #     min_index += 1
        # while min_index < self.memo_len and self.memo_lst[min_index] is None:
        #     min_index += 1
        #
        # while min_index < self.memo_len and self.is_fixed[min_index]:
        #     min_index += 1
        # while min_index < self.memo_len and self.memo_lst[min_index] is None:
        #     min_index += 1
        # print("min_index", min_index)

        if min_index == self.memo_len:
            # if self.is_fixed[min_index]:
            # 全部都被框柱了
            if self.now_index < self.input_lst_len:
                self.is_fixed = [False for i in range(self.memo_len)]
                min_index = 0
            # return -1
            else:
                return -1

        for i in range(self.memo_len):
            if self.is_fixed[i]: continue
            if type(self.memo_lst[i]) != int: continue
            # if type(self.memo_lst[min_index]) != int or type(self.memo_lst[i]) != int: continue
            try:
                if self.memo_lst[min_index] > self.memo_lst[i]:
                    min_index = i
                    # https://www.runoob.com/python/python-exceptions.html
            except  TypeError:
                print("self.memo_lst[min_index]", self.memo_lst[min_index])
                print("self.memo_lst[i]", self.memo_lst[i])
                raise

                # https://www.runoob.com/python/python-func-type.html
        if self.is_fixed[min_index]: return -1
        return min_index


# main
# rs = ReplaceSelect([5, 19, 25, 45, 30, 24, 15, 60, 16, 27, 1], 5)
# rs.run()

